#pragma once

#include <Initguid.h>
#include <Mfidl.h>
#include <shlwapi.h>
#include <mfapi.h>
#include <evr.h>
#include "Display.h"

namespace core::display::mf{
    enum MFPlayStatus{
        WaitForResponce = PlayStatus::_ + 1,
        Closing,
        Closed
    };

    namespace res = util::resource;

    class MFPlayer : public AbstractPlayer, IMFAsyncCallback{
    public:
        ~MFPlayer();

        STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
        STDMETHODIMP_(ULONG) AddRef();
        STDMETHODIMP_(ULONG) Release();
        STDMETHODIMP GetParameters(DWORD*, DWORD*)
        {
            // Implementation of this method is optional.
            return E_NOTIMPL;
        }
        STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);

        HRESULT HandleEvent(IMFMediaEvent * pEventPtr);

        HRESULT Shutdown();

        HRESULT PrepareSource(PCWSTR sUrl);

        HRESULT PrepareSource(res::BinFile* file);

        HRESULT PrepareToPlay();
        
        HRESULT Stop();

        static HRESULT CreateMFPlayer(HWND wnd, MFPlayer ** ppPlayer);

        virtual HRESULT Paint();

        virtual HRESULT Play();

        virtual void Reset();

        virtual PlayStatus GetStatus();

        virtual D2D1_RECT_F GetRect();

        virtual bool GetCurrentFrameD2DBitmap(ID2D1Bitmap ** ppbmp);

        static UINT mfplayer_count;
    protected:
        void ClearWhatItPaint();
        MFPlayer(HWND playon_wnd);
        void Initialize();

        HRESULT CreateSession();

        HRESULT CloseSession();

        virtual HRESULT OnTopologyStatus(IMFMediaEvent *pEvent);

        virtual HRESULT OnPresentationEnded(IMFMediaEvent *pEvent);

        virtual HRESULT OnSessionEnded(IMFMediaEvent *pEvent);

        virtual HRESULT OnNewPresentation(IMFMediaEvent *pEvent);

        static HRESULT CreateMediaSinkActivate(IMFStreamDescriptor *pSourceSD, HWND hVideoWindow, IMFActivate **ppActivate);

        HRESULT PrepareTopology(IMFPresentationDescriptor** ppPd);

        HRESULT StartPlayback();

    private:
        long ref_count;
        IMFByteStream * pVideoStream;
        IMFMediaSource * pSource;
        IMFMediaSession * pSession;
        HWND wnd;
        HDC draw_wnd;
        MFPlayStatus stats;
        IMFVideoDisplayControl * pDisplay;
        // HWND hwndEvent;

        std::condition_variable has_stop;
    };
}
